<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
 * auth
 *
 * @author Mathew Davies <leveldesign.info@gmail.com>
 * @copyright Copyright (c) 1 June 2008, Mathew Davies
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 * @version 1.4
 * @since 1.0
 **/
class auth extends auth_db
{
	/**
	 * __construct
	 *
	 * @access public
	 * @param void
	 * @return void
	 **/
	function __construct()
	{
		$this->ci =& get_instance();

		$this->ci->config->load('auth');
		$auth = $this->ci->config->item('auth');

		foreach($auth as $key => $value)
		{
			$this->$key = $value;
		}

		$this->ci->load->library('email', $this->mail);
	}

	/**
	 * register
	 *
	 * @access public
	 * @param string $username Username
	 * @param string $password Password
	 * @param string $email Valid email address
	 * @param string $question Secret question
	 * @param string $answer Answer to secret question
	 * @return mixed
	 **/
	public function register ($email, $password, $first_name, $last_name)
	{
		# Generate dynamic salt
		$hash = sha1(microtime());

		# Insert the salt into database
		$this->ci->db->set('hash', $hash);

		# Hash password
		$password_enc = sha1($this->salt.$hash.$password);

		//format first name
		$formatted_first_name = '';
		$fn = explode(' ', $first_name);
		for($i=0;$i<count($fn);$i++)
		{
			$formatted_first_name .= ucfirst(strtolower($fn[$i])).' ';
		}
		$formatted_first_name = trim($formatted_first_name);

		//format last name
		$formatted_last_name = '';
		$ln = explode(' ', $last_name);
		for($i=0;$i<count($ln);$i++)
		{
			$formatted_last_name .= ucfirst(strtolower($ln[$i])).' ';
		}
		$formatted_last_name = trim($formatted_last_name);

		$data = array
				(
				'email' 	=> $email,
				'password' 	=> $password_enc,
				'group_id'	=> $this->default_group,
				'first_name'    => $formatted_first_name,
				'last_name'     => $formatted_last_name,
				'created_on' => now()
		);

		$this->ci->db->set($data);

		/**
		 * Optional Columns Start
		 **/
		if (!empty($this->optional_columns))
		{
			foreach($this->optional_columns as $key)
			{
				if (!$this->ci->input->post($key))
				{
					$optional[$key] = null;
				}
				else
				{
					$optional[$key] = $this->ci->input->post($key);
				}
			}

			$this->ci->db->set($optional);
		}
		/**
		 * Optional Columns Finish
		 **/


		if (!$this->email_activation)
		{
			// Insert information into the users table
			$this->ci->db->insert($this->users_table);

			// Automatic login
			$this->login($email, $password);

			// Insert first and last name into users_profile table
			// Will disable this first because we are not using the user profile
			// table yet. We will need this when more data regarding the user is
			// necessary
			$this->ci->db->insert($this->users_profile_table, array('first_name' => $first_name, 'last_name' => $last_name, 'user_id' => $this->ci->session->userdata('id')));

			return 'REGISTRATION_SUCCESS';
		}

		else
		{
			# Generate activation code
			$key = sha1(microtime());

			$this->ci->db->set('activation_code', $key);
			$this->ci->db->insert($this->users_table);

			$m = str_replace('{activation_code}', $key, $this->email_activation_message);
			$message = str_replace('{base_url}', base_url(), $m);

			$this->ci->email->from($this->mail_from_email, $this->mail_from_name);
			$this->ci->email->to($email);
			$this->ci->email->subject($this->email_activation_subject);
			$this->ci->email->message($message);
			$this->ci->email->send();

			//echo $this->ci->email->print_debugger();

			return 'REGISTRATION_SUCCESS_EMAIL';
		}

		return false;
	}

	/**
	 * admin_register
	 *
	 * @access public
	 * @author Chris Bautista <chris@bautista.me>
	 * @param string $email Email
	 * @param string $password Password
	 * @param string $first_name First Name
	 * @param string $last_name Last Name
	 * @param bool $activation Determines if the user needs to activate the email or not
	 * @return mixed
	 **/
	public function admin_register($email, $password, $first_name, $last_name, $activation = 'FALSE')
	{
		# Generate dynamic salt
		$hash = sha1(microtime());

		# Insert the salt into database
		$this->ci->db->set('hash', $hash);

		# Hash password
		$password_enc = sha1($this->salt.$hash.$password);

		//format first name
		$formatted_first_name = '';
		$fn = explode(' ', $first_name);
		for($i=0;$i<count($fn);$i++)
		{
			$formatted_first_name .= ucfirst(strtolower($fn[$i])).' ';
		}
		$formatted_first_name = trim($formatted_first_name);

		//format last name
		$formatted_last_name = '';
		$ln = explode(' ', $last_name);
		for($i=0;$i<count($ln);$i++)
		{
			$formatted_last_name .= ucfirst(strtolower($ln[$i])).' ';
		}
		$formatted_last_name = trim($formatted_last_name);

		$data = array
				(
				'email' 	=> $email,
				'password' 	=> $password_enc,
				'group_id'	=> $this->default_group,
				'first_name'    => $formatted_first_name,
				'last_name'     => $formatted_last_name,
				'created_on' => now()
		);

		$this->ci->db->set($data);

		/**
		 * Optional Columns Start
		 **/
		if (!empty($this->optional_columns))
		{
			foreach($this->optional_columns as $key)
			{
				if (!$this->ci->input->post($key))
				{
					$optional[$key] = null;
				}
				else
				{
					$optional[$key] = $this->ci->input->post($key);
				}
			}

			$this->ci->db->set($optional);
		}
		/**
		 * Optional Columns Finish
		 **/


		if ($activation == 'FALSE')
		{
			// Insert information into the users table
			$this->ci->db->insert($this->users_table);

			// Insert first and last name into users_profile table
			$this->ci->db->insert($this->users_profile_table, array('first_name' => $first_name, 'last_name' => $last_name, 'user_id' => $this->ci->session->userdata('id')));

			// Email the user with email and password details
			$m = str_replace('{email}', $email, $this->email_admin_registered_message);
			$m2 = str_replace('{password}', $password, $m);
			$message = str_replace('{base_url}', base_url(), $m2);

			$this->ci->email->from($this->mail_from_email, $this->mail_from_name);
			$this->ci->email->to($email);
			$this->ci->email->subject($this->email_admin_registered_subject);
			$this->ci->email->message($message);
			$this->ci->email->send();

			return 'REGISTRATION_SUCCESS';
		}
		else
		{
			# Generate activation code
			$key = sha1(microtime());

			$this->ci->db->set('activation_code', $key);
			$this->ci->db->insert($this->users_table);

			$m = str_replace('{email}', $email, $this->email_admin_activation_message);
			$m2 = str_replace('{password}', $password, $m);
			$m3 = str_replace('{key}', $key, $m2);
			$message = str_replace('{base_url}', base_url(), $m3);

			$m = str_replace('{activation_code}', $key, $this->email_admin_activation_message);

			$this->ci->email->from($this->mail_from_email, $this->mail_from_name);
			$this->ci->email->to($email);
			$this->ci->email->subject($this->email_admin_activation_subject);
			$this->ci->email->message($message);
			$this->ci->email->send();

			return 'REGISTRATION_SUCCESS_EMAIL';
		}

		return false;
	}

	/**
	 * resend_activation_email
	 *
	 * @access public
	 * @author Chris Bautista <chris@bautista.me>
	 * @param string $user_id User ID
	 * @return void
	 **/
	public function resend_activation_email($user_id)
	{
		$u = $this->get_user($user_id);

		$message = str_replace('{activation_code}', $u->activation_code, $this->email_activation_message);

		$this->ci->email->from($this->mail_from_email, $this->mail_from_name);
		$this->ci->email->to($u->email);
		$this->ci->email->subject($this->email_activation_subject);
		$this->ci->email->message($message);
		$this->ci->email->send();
	}

	/**
	 * login
	 *
	 * @access public
	 * @param string $email Vaild email address
	 * @param string $password Password
	 * @return mixed
	 **/
	public function login ($email, $password)
	{
		# Grab hash, password, id, activation_code and banned_id from database.
		$result = $this->_login($this->users_table, $this->banned_table, $email);

		if ($result)
		{

			if($result->activation_code != '')
			{
				//$this->ci->session->set_flashdata('login', 'Your Account is Not Activated.');
				$auth['status'] = 'NOT_ACTIVATED';
				$auth['masked_user_id'] = rand(1,9).rand(1,9).$result->id.rand(1,9).rand(1,9);
				$auth['not_activated_key'] = sha1($result->activation_code);
				$auth['message'] = 'Your Account is Not Activated.';
				return $auth;
			}
			elseif($result->banned_id != 0)
			{
				//$this->ci->session->set_flashdata('login', 'Your Account has been banned for the following reason : '.$result->reason);
				$auth['status'] = 'BANNED';
				$auth['reason'] = 'Your account has been banned for the following reason: '.$result->reason;
				return $auth;
			}
			elseif($result->activation_code == '' && $result->banned_id == 0)
			{
				$password = sha1($this->salt.$result->hash.$password);

				if ($password === $result->password)
				{
					$userdata = array(
							'id'=> $result->id,
							'group_id'=> $result->group_id,
							'first_name'=> $result->first_name,
							'timezone'=> $result->timezone
					);
					$this->ci->session->set_userdata($userdata);
					$this->_update_last_login($this->users_table, $result->id);
					$auth['status'] = TRUE;
					return $auth;
				}
				else
				{
					$auth['status'] = FALSE; // WRONG PASSWORD
					return $auth;
				}
			}
		}
		else
		{
			$auth['status'] = FALSE; // NO EMAIL EXISTS
			return $auth;
		}
	}

	/**
	 * check_password
	 *
	 * @access public
	 * @param string $password
	 * @param string $password Password
	 * @return mixed
	 **/
	public function check_password($password)
	{
		$result = $this->_get_user_password_data($this->users_table, $this->session->userdata('id'));
		$check_password = sha1($this->salt.$result->hash.$password);

		if ($check_password == $result->password)
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}

	/**
	 * change_password
	 *
	 * Changes the password
	 *
	 * @author Chris Bautista <chris@bautista.me>
	 * @access public
	 * @param $old_password Original password of the account
	 * @param $new_password New password
	 * @return bool
	 **/
	public function change_password($old_password,$new_password)
	{
		$result = $this->_get_user_password_data($this->users_table, $this->ci->session->userdata('id'));

		$old_password = sha1($this->salt.$result->hash.$old_password);

		if($result->password === $old_password)
		{
			// Generate dynamic salt
			$hash = sha1(microtime());

			// Insert the salt into database
			$this->ci->db->set('hash', $hash);

			// Hash password
			$password_enc = sha1($this->salt.$hash.$new_password);

			$this->ci->db->set('password', $password_enc);

			// Note: using session ID to change password so that only the account
			// owner can change the password
			$this->ci->db->where('id', $this->ci->session->userdata('id'));
			$this->ci->db->update($this->users_table);

			// Flash data that password has changed
			// @TODO: Include this message to the "auth" config file
			$this->ci->session->set_flashdata('dashboard_message', 'Your password has been changed');

			return TRUE;
		}
		else
		{
			// Flash data that there is an error. Next step should redirect you
			// back to the change_password page
			// @TODO: Include this message to the "auth" config file
			$this->ci->session->set_flashdata('error_message', 'You need to enter the correct original password');

			return FALSE;
		}


	}

	/**
	 * ban_user
	 *
	 * Changes the password
	 *
	 * @author Chris Bautista <chris@bautista.me>
	 * @access public
	 * @param $user_id User ID
	 * @param $reason Reason for banning
	 * @return void
	 **/
	public function ban_user($user_id,$reason)
	{
		$data = array(
				'user_id' => $user_id,
				'reason' => $reason,
				'time' => now()
		);
		$this->ci->db->insert($this->banned_table, $data);

		$updata_data = array(
				'banned_id' => $this->ci->db->insert_id()
		);
		$this->ci->db->where('id', $user_id);
		$this->ci->db->update($this->users_table, $updata_data);

		// grab the user's details to generate message
		$query = $this->ci->db->select('first_name, last_name, email')
				->from($this->users_table)
				->where('id', $user_id)
				->limit(1)
				->get();
		$q = $query->row();

		$name = $q->first_name.' '.$q->last_name;
		$email = $q->email;
		
		// @TODO: email the user that he/she is banned
		$m = str_replace('{name}', $name, $this->banned_email_message);
		$message = str_replace('{reason}', $reason, $m);

		$this->ci->email->from($this->mail_from_email, $this->mail_from_name);
		$this->ci->email->to($email);
		$this->ci->email->subject($this->banned_email_subject);
		$this->ci->email->message($message);
		if( ! $this->ci->email->send())
		{
			$this->ci->email->print_debugger();
			$this->ci->session->set_flashdata('message', $name.' ['.$email.'] has been banned but the email was not sent successfully');
		}
		else
		{
			$this->ci->session->set_flashdata('message', $name.' ['.$email.'] has been banned.');
		}

	}

	public function unban_user($user_id)
	{
		$query = $this->ci->db->select('banned_id, first_name, last_name, email')
				->from($this->users_table)
				->where('id', $user_id)
				->limit(1)
				->get();
		$q = $query->row();

		$banned_id = $q->banned_id;
		$name = $q->first_name.' '.$q->last_name;
		$email = $q->email;

		if($banned_id != 0)
		{
			// update users table to take out the ban id
			$user_data = array(
					'banned_id' => 0,
			);
			$this->ci->db->where('id', $user_id);
			$this->ci->db->update($this->users_table, $user_data);

			// update ban table to insert end time of ban - for history purposes
			$ban_data = array(
					'time_end' => now()
			);
			$this->ci->db->where('id', $banned_id);
			$this->ci->db->update($this->banned_table, $ban_data);

			// set flashdata message to be displayed back in users/view
			$this->ci->session->set_flashdata('message', $name.' ['.$email.'] has been unbanned.');

			// @TODO: email user that their account has been unbanned
		}
		else
		{
			$this->ci->session->set_flashdata('message', 'User is not banned');
		}
	}

	/**
	 * admin_login
	 *
	 * A copy of the "login" function - couldn't remember why I did this but I
	 * have it integrated now with the admin login section
	 *
	 * @author Chris Bautista <chris@bautista.me>
	 * @access public
	 * @param void
	 * @return bool
	 **/
	public function admin_login ($email, $password)
	{
		$result = $this->_login($this->users_table, $this->banned_table, $email);

		if ($result)
		{
			if($result->group_id == 1)
			{
				if($result->activation_code != '')
				{
					$this->ci->session->set_flashdata('login', 'Your Account is Not Activated.');
					return 'NOT_ACTIVATED';
				}
				elseif($result->banned_id != 0)
				{
					$this->ci->session->set_flashdata('login', 'Your Account has been banned for the following reason : '.$result->reason);
					return 'BANNED';
				}
				elseif($result->activation_code == '' && $result->banned_id == 0)
				{
					$password = sha1($this->salt.$result->hash.$password);

					if ($password === $result->password)
					{
						$this->ci->session->set_userdata(array('id'=> $result->id));
						$this->_update_last_login($this->users_table, $result->id);

						return true;
					}
					else
					{
						return 'WRONG_PASSWORD';
					}
				}
			}
			else
			{
				$this->ci->session->set_flashdata('login', 'You do not have permission to access this page');
				return 'NO_PERMISSION';
			}
		}
		else
		{
			return FALSE;
		}
	}

	/**
	 * logged_in
	 *
	 * @access public
	 * @param void
	 * @return bool
	 **/
	public function logged_in ()
	{
		return $var = ($this->ci->session->userdata('id')) ? true : false;
	}

	public function admin_logged_in ()
	{
		if($this->ci->session->userdata('group_id') == 1 && $this->ci->session->userdata('id'))
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}

	/**
	 * logout
	 *
	 * @access public
	 * @param void
	 * @return void
	 **/
	public function logout ()
	{
		$this->ci->session->unset_userdata('id');
		$this->ci->session->sess_destroy();
	}

	/**
	 * activate
	 *
	 * @access public
	 * @param string $activation_code
	 * @return bool
	 **/
	public function activate ($activation_code)
	{
		$activate = $this->_activate($this->users_table, $activation_code);

		if($activate != FALSE)
		{
			// email the user that the account is activated
			$login_link = base_url().'/users/login';
			$m = str_replace('{name}', $activate['name'], $this->activated_email_message);
			$message = str_replace('{login_link}', $login_link, $m);

			$this->ci->email->from($this->mail_from_email, $this->mail_from_name);
			$this->ci->email->to($activate['email']);
			$this->ci->email->subject($this->activated_email_subject);
			$this->ci->email->message($message);
			if( ! $this->ci->email->send())
			{
				$this->ci->session->set_flashdata('message', 'The email '.$activate['email'].' has been activated. But the welcome email was not sent.');
			}
			else
			{
				$this->ci->session->set_flashdata('message', 'The email '.$activate['email'].' has been activated.');
			}

			return TRUE;
		}
		else
			return FALSE;

		//return $var = ($activate) ? true : false;
	}

	/**
	 * get_group
	 *
	 * @access public
	 * @param string $id Users id
	 * @return string
	 **/
	public function get_group($id)
	{
		return $this->_get_group($this->groups_table, $this->users_table, $id);
	}

	/**
	 * check_username
	 *
	 * @access public
	 * @param string $username Username
	 * @return bool
	 **/
	public function check_username($username)
	{
		return $this->_check_username($this->users_table, $username);
	}

	/**
	 * check_email
	 *
	 * @access public
	 * @param string $email Valid email address
	 * @return bool
	 **/
	public function check_email($email)
	{
		return $this->_check_email($this->users_table, $email);
	}

	/**
	 * email_activation_code
	 *
	 * Resends the activation link to the given email if the parameters are
	 * correct. $not_activated_key is an encrypted version of the actual activation
	 * code.
	 *
	 * @access public
	 * @param string $masked_user_id User ID with mask - 2 random numbers attached to the beginning and ending of the real user ID xx{user_id}xx
	 * @param string $not_activated_key Encrypted activation code using sha1
	 * @return bool
	 **/
	public function email_activation_code($masked_user_id,$not_activated_key)
	{
		$user_id = substr($masked_user_id, 2, -2);
		$user = $this->_get_user_email_activation_code($this->users_table, $user_id);
		if($user != FALSE)
		{
			if(sha1($user->activation_code) == $not_activated_key)
			{
				// email the activation link
				$m = str_replace('{activation_code}', $user->activation_code, $this->email_activation_message);
				$message = str_replace('{base_url}', base_url(), $m);

				$this->ci->email->from($this->mail_from_email, $this->mail_from_name);
				$this->ci->email->to($user->email);
				$this->ci->email->subject($this->email_activation_subject);
				$this->ci->email->message($message);
				$this->ci->email->send();

				return TRUE;
			}
			else
			{
				return FALSE;
			}
		}
		else
			return FALSE;
	}

	/**
	 * get_users
	 *
	 * Grabs the whole list of users from the database
	 *
	 * @author Chris Bautista <chris@bautista.me>
	 * @access public
	 * @param void
	 * @return mixed
	 **/
	public function get_users()
	{
		$users_tbl = $this->users_table;
		$groups_tbl = $this->groups_table;

		$query = $this->ci->db->select($users_tbl.'.id as id, '.
				$users_tbl.'.email as email, '.
				$users_tbl.'.first_name as first_name, '.
				$users_tbl.'.last_name as last_name, '.
				$users_tbl.'.last_login as last_login, '.
				$users_tbl.'.created_on as created_on, '.
				$groups_tbl.'.title as account_type')
				->from($users_tbl)
				->join($groups_tbl, $users_tbl.'.group_id = '.$groups_tbl.'.id', 'left')
				->get();

		return $query->result();
	}

	/**
	 * get_users_page
	 *
	 * Grabs the list of users from the database with pagination parameters
	 *
	 * @author Chris Bautista <chris@bautista.me>
	 * @access public
	 * @param int $page Page number|Offset
	 * @param int $per_page Number of items per page|Limit
	 * @return mixed
	 **/
	public function get_users_page($page, $per_page)
	{
		$users_tbl = $this->users_table;
		$groups_tbl = $this->groups_table;
		$banned_tbl = $this->banned_table;

		$query = $this->ci->db->select($users_tbl.'.id as id, '.
				$users_tbl.'.email as email, '.
				$users_tbl.'.first_name as first_name, '.
				$users_tbl.'.last_name as last_name, '.
				$users_tbl.'.banned_id as banned_id, '.
				$banned_tbl.'.reason as banned_reason, '.
				$users_tbl.'.last_login as last_login, '.
				$users_tbl.'.activation_code as activation_code, '.
				$users_tbl.'.timezone as timezone, '.
				$users_tbl.'.created_on as created_on, '.
				$groups_tbl.'.title as account_type')
				->from($users_tbl)
				->join($groups_tbl, $users_tbl.'.group_id = '.$groups_tbl.'.id', 'left')
				->join($banned_tbl, $users_tbl.'.banned_id = '.$banned_tbl.'.id', 'left')
				->limit($per_page, $page)
				->get();

		foreach($query->result() as $q)
		{
			if($q->banned_id > 0)
			{
				$q->status = '<span title="'.$q->banned_reason.'">Banned</span>';
				$q->ban_link = '<a href="'.base_url().'users/unban/'.$q->id.'">Unban</a>';
			}
			elseif($q->activation_code == '')
			{
				$q->status = 'Activated';
				$q->ban_link = '<a href="'.base_url().'users/ban/'.$q->id.'">Ban</a>';
			}
			elseif($q->activation_code != '')
			{
				$q->status = 'Not Activated';
				$q->ban_link = '<a href="'.base_url().'users/ban/'.$q->id.'">Ban</a>';
			}
		}

		return $query->result();
	}

	/**
	 * get_users_total
	 *
	 * Grabs the total number of users in the database - used for table
	 * pagination purposes
	 *
	 * @author Chris Bautista <chris@bautista.me>
	 * @access public
	 * @param void
	 * @return int Number of users in the database
	 **/
	public function get_users_total()
	{
		$query = $this->ci->db->get($this->users_table);

		return $query->num_rows();
	}

	/**
	 * get_users
	 *
	 * Grabs all data of a user - can be used for editing purposes or profile
	 * building
	 *
	 * @author Chris Bautista <chris@bautista.me>
	 * @access public
	 * @param int $user_id user id
	 * @return mixed
	 **/
	public function get_user($user_id)
	{
		$users_tbl = $this->users_table;
		$groups_tbl = $this->groups_table;
		$users_profile_tbl = $this->users_profile_table;
		$countries_tbl = $this->countries_table;
		$banned_tbl = $this->banned_table;

		$query = $this->ci->db->select($users_tbl.'.id as id, '.
				$users_tbl.'.email as email, '.
				$users_tbl.'.first_name as first_name, '.
				$users_tbl.'.last_name as last_name, '.
				$users_tbl.'.group_id as group_id, '.
				$users_tbl.'.last_login as last_login, '.
				$users_tbl.'.created_on as created_on, '.
				$users_tbl.'.timezone as timezone, '.
				$users_tbl.'.country_id as country_id, '.
				$users_tbl.'.activation_code as activation_code, '.
				$users_tbl.'.banned_id as banned_id, '.
				$banned_tbl.'.reason as banned_reason, '.
				$countries_tbl.'.country as country_name, '.
				$groups_tbl.'.title as account_type')
				->from($users_tbl)
				->where($users_tbl.'.id', $user_id)
				->join($groups_tbl, $users_tbl.'.group_id = '.$groups_tbl.'.id', 'left')
				->join($countries_tbl, $users_tbl.'.country_id = '.$countries_tbl.'.id', 'left')
				->join($banned_tbl, $users_tbl.'.banned_id = '.$banned_tbl.'.id', 'left')
				->limit(1)
				->get();

		$q = $query->row();

		$q->activate_link = ''; // nothing - just pre-defines the activate link

		if($q->banned_id > 0)
		{
			$q->status = 'Banned - '.$q->banned_reason;
			$q->ban_link = '<a href="'.base_url().'users/unban/'.$q->id.'">Unban</a>';
		}
		elseif($q->activation_code == '')
		{
			$q->status = 'Activated';
			$q->ban_link = '<a href="'.base_url().'users/ban/'.$q->id.'">Ban</a>';
		}
		elseif($q->activation_code != '')
		{
			$q->status = 'Not Activated';
			$q->ban_link = '<a href="'.base_url().'users/ban/'.$q->id.'">Ban</a>';
			// @TODO: continue building activation link for admins
			// try passing another variable at the 4th uri saying you are admin
			$q->activate_link = '<a href="'.base_url().'users/activate/'.$q->activation_code.'/admin">Activate</a> | ';
		}
		return $q;
	}

	/**
	 * get_groups_dropdown
	 *
	 * Builds an array of the user groups that can be used to form dropdown
	 * menus
	 *
	 * @author Chris Bautista <chris@bautista.me>
	 * @access public
	 * @param void
	 * @return mixed
	 **/
	public function get_groups_dropdown()
	{
		$query = $this->ci->db->get($this->groups_table);

		foreach($query->result() as $q)
		{
			$groups[$q->id] = $q->title;
		}

		return $groups;
	}

	/**
	 * update_user
	 *
	 * Updates a user's data in the database
	 *
	 * @author Chris Bautista <chris@bautista.me>
	 * @access public
	 * @param int $user_id user id
	 * @param mixed $user_data array of data to update
	 * @return void
	 **/
	public function update_user($user_id, $user_data)
	{
		// format the first and last name
		// format first name
		$formatted_first_name = '';
		$fn = explode(' ', $user_data['first_name']);
		for($i=0;$i<count($fn);$i++)
		{
			$formatted_first_name .= ucfirst(strtolower($fn[$i])).' ';
		}
		$user_data['first_name'] = trim($formatted_first_name);

		// format last name
		$formatted_last_name = '';
		$ln = explode(' ', $user_data['last_name']);
		for($i=0;$i<count($ln);$i++)
		{
			$formatted_last_name .= ucfirst(strtolower($ln[$i])).' ';
		}
		$user_data['last_name'] = trim($formatted_last_name);

		$this->ci->db->where('id', $user_id);
		$this->ci->db->update($this->users_table, $user_data);

		// if the user updated his/her own account, change the session data
		if($user_id == $this->ci->session->userdata('id'))
		{
			// update the first name in the session
			$this->ci->session->unset_userdata('first_name');
			$this->ci->session->set_userdata('first_name', $user_data['first_name']);
			// update the timezone in the session
			$this->ci->session->unset_userdata('timezone');
			$this->ci->session->set_userdata('timezone', $user_data['timezone']);
		}

		// Set flash cookie that user profile has been updated
		//$this->ci->session->set_flashdata('dashboard_message', 'Your profile has been updated');

	}

	public function get_countries_dropdown()
	{
		$query = $this->ci->db->get($this->countries_table);

		$countries['0'] = 'Choose a country';
		if($query->num_rows() > 0)
		{
			foreach($query->result() as $q)
			{
				$countries[$q->id] = $q->country;
			}
		}
		else
			$countries = '';

		return $countries;
	}

	public function delete_user($user_id)
	{
		$query = $this->ci->db->select('first_name, last_name, email')
				->from($this->users_table)
				->where('id', $user_id)
				->limit(1)
				->get();

		if($query->num_rows() > 0)
		{
			$q = $query->result();
			// delete the user
			$this->_delete_user($this->users_table, $this->users_profile_table, $this->banned_table, $user_id);
			// set flashdata message for "view users" page
			$this->ci->session->set_flashdata('message', $q->first_name.' '.$q->last_name.' ['.$q->email.'] has been deleted');
			return TRUE;
		}
		else
			return FALSE;
	}

	public function get_ban_history($user_id)
	{
		$query = $this->ci->db->get_where($this->banned_table, array('user_id' => $user_id));

		if($query->num_rows() > 0)
		{
			return $query->result();
		}
		else
		{
			return FALSE;
		}
	}

	public function confirm_password_reset($email)
	{
		$query = $this->ci->db->select('id')
				->where('email', $email)
				->where('banned_id', 0)
				->from($this->users_table)
				->limit(1)
				->get();

		if($query->num_rows() > 0)
		{
			$q = $query->row();

			$forgotten_password_code = sha1(microtime());
			
			$this->ci->db->where('id',$q->id)
					->update($this->users_table, array('forgotten_password_code' => $forgotten_password_code));

			// build reset password link
			$masked_user_id = rand(1,9).rand(1,9).$q->id.rand(1,9).rand(1,9);
			$reset_password_link = base_url().'users/reset_password/'.$masked_user_id.'/'.$forgotten_password_code;

			// email the user the link where he can reset his password
			$message = str_replace('{reset_password_link}', $reset_password_link, $this->confirm_reset_password_message);

			$this->ci->email->from($this->mail_from_email, $this->mail_from_name);
			$this->ci->email->to($email);
			$this->ci->email->subject($this->confirm_reset_password_subject);
			$this->ci->email->message($message);
			$this->ci->email->send();

			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}

	public function reset_password($masked_user_id,$forgotten_password_code)
	{
		$user_id = substr($masked_user_id, 2, -2);

		$query = $this->ci->db->select('forgotten_password_code, email')
				->from($this->users_table)
				->where('id', $user_id)
				->limit(1)
				->get();

		if($query->num_rows() > 0)
		{
			$q = $query->row();
			if($q->forgotten_password_code == $forgotten_password_code)
			{
				$this->ci->load->helper('string');
				// reset the password
				$password = random_string('alnum', 10);

				# Generate dynamic salt
				$hash = sha1(microtime());

				# Hash password
				$password_enc = sha1($this->salt.$hash.$password);

				$update_data = array(
					'hash' => $hash,
					'password' => $password_enc
				);
				$this->ci->db->where('id', $user_id)
						->update($this->users_table, $update_data);

				// email the user with their updated password
				$message = str_replace('{password}', $password, $this->reset_password_message);

				$this->ci->email->from($this->mail_from_email, $this->mail_from_name);
				$this->ci->email->to($q->email);
				$this->ci->email->subject($this->reset_password_subject);
				$this->ci->email->message($message);
				$this->ci->email->send();

				return TRUE;
			}
			else
			{
				return FALSE;
			}
		}
		else
			return FALSE;
	}

}

/**
 * auth_db
 *
 * @author Mathew Davies <leveldesign.info@gmail.com>
 * @copyright Copyright (c) 1 June 2008, Mathew Davies
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 * @version 1.4
 * @since 1.0
 **/
class auth_db
{

	/**
	 * _activate
	 *
	 * @access protected
	 * @param string $users_tbl Users table
	 * @param string $code Email activation code
	 * @return mixed
	 **/
	protected function _activate ($users_tbl, $code)
	{
		$query = $this->ci->db->select('id, first_name, last_name, email')
				->where('activation_code', $code)
				->from($users_tbl)
				->limit(1)
				->get();

		if($query->num_rows() > 0)
		{
			$q = $query->row();

			$user_id = $q->id;
			$activate['name'] = $q->first_name.' '.$q->last_name;
			$activate['email'] = $q->email;

			$this->ci->db->where($users_tbl.'.id', $user_id)
					->update($users_tbl, array($users_tbl.'.activation_code' => ''));

			return $activate;
		}
		else
			return FALSE;
		//return $var = ($this->ci->db->affected_rows() > 0) ? true : false;
	}

	/**
	 * _insert_new_password
	 *
	 * @access protected
	 * @param string $users_tbl Users table
	 * @param string $password New password
	 * @param integer $question_id Question id
	 * @return bool
	 **/
	protected function _insert_new_password($users_tbl, $password, $question_id)
	{
		# New hash
		$hash = sha1(microtime());

		# New hashed password
		$password = sha1($this->salt.$hash.$password);

		$data = array(
				$users_tbl.'.forgotten_password_code' => '0',
				$users_tbl.'.password' => $password,
				$users_tbl.'.hash' => $hash
		);

		$this->ci->db->where($users_tbl.'.question_id', $question_id)->update($users_tbl, $data);

		return $var = ($this->ci->db->affected_rows() > 0) ? true : false;
	}

	/**
	 * _insert_forgotten_code
	 *
	 * @access protected
	 * @param string $users_tbl Users table
	 * @param string $key Email verification code
	 * @param string $email Users email address
	 * @return bool
	 **/
	protected function _insert_forgotten_code($users_tbl, $key, $email)
	{
		$this->ci->db->where($users_tbl.'.email', $email)->update($users_tbl, array('forgotten_password_code' => $key));

		return $var = ($this->ci->db->affected_rows() > 0) ? true : false;
	}

	/**
	 * _check_forgotten_code
	 *
	 * @access protected
	 * @param string $users_tbl Users table
	 * @param string $email Valid email address
	 * @return bool
	 **/
	protected function _check_forgotten_code($users_tbl, $email)
	{
		$i = $this->ci->db->select($users_tbl.'.forgotten_password_code')->from($users_tbl)->where($users_tbl.'.email', $email)->get();

		return $var = ($i->num_rows() > 0) ? true : false;
	}

	/**
	 * _remove_forgotten_code
	 *
	 * @access protected
	 * @param string $users_tbl Users table
	 * @param string $key Email verification code
	 * @return bool
	 **/
	protected function _remove_forgotten_code($users_tbl, $key)
	{
		$this->ci->db->where($users_tbl.'.forgotten_password_code', $key)->update($users_tbl, array($users_tbl.'.forgotten_password_code' => 0));

		return $var = ($this->ci->db->affected_rows() > 0) ? true : false;
	}

	/**
	 * _check_username
	 *
	 * @access protected
	 * @param string $users_tbl Users table
	 * @param string $username Username
	 * @return bool
	 **/
	protected function _check_username ($users_tbl, $username)
	{
		$i = $this->ci->db->select($users_tbl.'.username')->from($users_tbl)->where($users_tbl.'.username', $username)->get();

		return $var = ($i->num_rows() > 0) ? true : false;
	}

	/**
	 * _check_email
	 *
	 * @access protected
	 * @param string $users_tbl Users table
	 * @param string $email Valid email address
	 * @return bool
	 **/
	protected function _check_email ($users_tbl, $email)
	{
		$i = $this->ci->db->select($users_tbl.'.email')->from($users_tbl)->where($users_tbl.'.email', $email)->get();

		return $var = ($i->num_rows() > 0) ? true : false;
	}

	/**
	 * _get_group
	 *
	 * @access protected
	 * @param string $groups_tbl Groups table
	 * @param string $users_tbl Users table
	 * @param integer $id Group id
	 * @return string
	 **/
	protected function _get_group ($groups_tbl, $users_tbl, $id)
	{
		$i = $this->ci->db->select($groups_tbl.'.title')
				->from($groups_tbl)
				->join($users_tbl, $groups_tbl.'.id = '.$users_tbl.'.group_id', 'left')
				->where($users_tbl.'.id', $id)
				->limit(1)
				->get();

		return $var = ($i->num_rows() > 0) ? $i->row()->title : false;
	}

	/**
	 * _login
	 *
	 * @access protected
	 * @param string $users_tbl Users table
	 * @param string $banned_tbl Banned table
	 * @param string $email Valid email address
	 * @return mixed
	 **/
	protected function _login ($users_tbl, $banned_tbl, $email)
	{
		$i = $this->ci->db->select($users_tbl.'.password, '.
				$users_tbl.'.first_name, '.
				$users_tbl.'.hash, '.
				$users_tbl.'.id, '.
				$users_tbl.'.activation_code, '.
				$users_tbl.'.banned_id, '.
				$users_tbl.'.group_id, '.
				$users_tbl.'.timezone, '.
				$banned_tbl.'.reason')
				->from($users_tbl)
				->join($banned_tbl, $users_tbl.'.banned_id = '.$banned_tbl.'.id', 'left')
				->where($users_tbl.'.email', $email)
				->limit(1)
				->get();

		return $var = ($i->num_rows() > 0) ? $i->row() : false;
	}

	protected function _update_last_login($users_tbl, $user_id)
	{
		$data = array(
				'last_login' => now()
		);
		$this->ci->db->where('id', $user_id);
		$this->ci->db->update($users_tbl, $data);
	}

	protected function _get_user_password_data($users_tbl, $user_id)
	{
		$i = $this->ci->db->select($users_tbl.'.password, '.
				$users_tbl.'.hash')
				->from($users_tbl)
				->where('id', $user_id)
				->limit(1)
				->get();

		return $var = ($i->num_rows() > 0) ? $i->row() : false;
	}

	protected function _get_user_email_activation_code($users_tbl, $user_id)
	{
		$query = $this->ci->db->select('activation_code, email')
				->from($users_tbl)
				->where('id', $user_id)
				->limit(1)
				->get();
		if($query->num_rows() > 0)
		{
			return $query->row();
		}
		else
		{
			return FALSE;
		}
	}

	protected function _delete_user($users_tbl, $users_profile_tbl, $banned_tbl, $user_id)
	{
		$this->ci->db->where('id', $user_id);
		$this->ci->db->delete($users_tbl);

		$this->ci->db->where('user_id', $user_id);
		$this->ci->db->delete($users_profile_tbl);

		$this->ci->db->where('user_id', $user_id);
		$this->ci->db->delete($banned_tbl);
	}
}